package com.sicong.common.util;

import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpUtil;
import com.sicong.common.enums.LogModuleEnum;
import com.sicong.common.annotation.Log;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 日志工具类
 *
 * @author chenww
 * @date 2020-12-03
 */
@Slf4j
public class LogUtil {

    public static void log(LogModuleEnum module, String ip, String method, String description) {
        log.info("=========================== 进入控制器 ===========================");
        log.info("模块：   {}", module.getName());
        log.info("请求用户：{}", getUsername());
        log.info("请求IP： {}", ip);
        log.info("请求方法：{}", method);
        log.info("方法描述：{}", description);
        log.info("==================================================================");
    }

    public static Map<String, Object> getLogInfo(ProceedingJoinPoint joinPoint) throws ClassNotFoundException {
        Map<String, Object> map = new HashMap<>(2);
        // 获取当前类名
        String className = joinPoint.getTarget().getClass().getName();
        // 获取当前方法名
        String methodName = joinPoint.getSignature().getName();
        // 获取当前方法参数
        Object[] arguments = joinPoint.getArgs();
        // 获取当前类的类对象
        Class<?> targetClass = Class.forName(className);
        // 获取当前类中的方法
        Method[] methods = targetClass.getMethods();
        String description = "";
        LogModuleEnum module = null;
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                // 获取方法所有参数的类型
                Class<?>[] cls = method.getParameterTypes();
                if (cls.length == arguments.length) {
                    if (method.isAnnotationPresent(Log.class)) {
                        Log log = method.getAnnotation(Log.class);
                        description = log.value();
                        module = log.module();
                        if (targetClass.isAnnotationPresent(Log.class)) {
                            Log moduleLog = targetClass.getAnnotation(Log.class);
                            if (moduleLog != null && module.getCode() == 0) {
                                module = moduleLog.module();
                            }
                        }
                        break;
                    }
                }
            }
        }
        map.put("module", module);
        map.put("description", description);
        return map;
    }

    /**
     * 获取 HttpServletRequest
     * @return HttpServletRequest
     */
    private static HttpServletRequest getRequest() {
        return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes()))
                .getRequest();
    }

    /**
     * 获取IP地址
     *
     * @return IP 地址
     */
    public static String getIpAddress() {
        HttpServletRequest request = getRequest();
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public static com.sicong.admin.entity.Log getLog() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects
                .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        com.sicong.admin.entity.Log log = new com.sicong.admin.entity.Log();
        log.setCreateBy(Objects.requireNonNull(getUsername()));
        log.setType("0");
        log.setRemoteAddr(getIpAddress());
        log.setRequestUri(URLUtil.getPath(request.getRequestURI()));
        log.setMethod(request.getMethod());
        log.setUserAgent(request.getHeader("user-agent"));
        log.setParams(HttpUtil.toParams(request.getParameterMap()));
        return log;
    }

    /**
     * 获取用户名称
     * @return 用户名称
     */
    private static String getUsername() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            return null;
        }
        return authentication.getName();
    }

}
